#include "my_include.h"
 

uint8_t flash_read(uint32_t address, uint8_t *buff, uint16_t len)
{
    memcpy(buff, (uint8_t *)(address), len);
    return true;
}

uint32_t xfdata[256];
uint8_t flash_write(uint32_t address, const uint8_t *buff, uint16_t len)
{
    uint8_t ret = true;
    uint32_t addr;
   
    uint16_t i;
    memset(xfdata, 0xFF, sizeof(xfdata));
    memcpy((uint8_t *)xfdata, buff, len);

    if (address % 4){
        return false;
    }
    FLASH_Unlock();
    addr = address;
    for (i = 0; i < (len+3)/4; i++){
        if (FLASH_COMPLETE != FLASH_ProgramWord(addr, xfdata[i])){
            ret = false;
            break;
        }
        addr += 4;
    }
    FLASH_Lock();
    return ret;
}
uint8_t flash_verify(uint32_t address, const uint8_t *buff, uint16_t len)
{
    uint8_t ret = true;
    uint8_t data[256];
    uint16_t i;

    flash_read(address, data, len);
    for (i = 0; i < len; i++){
        if (data[i] != buff[i]){
            ret = false;
            break;
        }
    }
    return ret;
}
uint8_t flash_protect(uint32_t address, uint16_t len)
{
    uint8_t ret = true;
    uint16_t pagecnt;
    uint32_t pageaddr;
    uint16_t i;
    pageaddr = (address / FLASH_PAGE_SIZE) * FLASH_PAGE_SIZE;   // page start address
    pagecnt = ((address % FLASH_PAGE_SIZE) + len) / FLASH_PAGE_SIZE;
    if (((address % FLASH_PAGE_SIZE) + len) % FLASH_PAGE_SIZE){
        pagecnt += 1;
    }
    FLASH_Unlock();
    for (i = 0; i < pagecnt; i++){
        if (FLASH_COMPLETE != FLASH_EnableWriteProtection(pageaddr + FLASH_PAGE_SIZE*i)){
            ret = false;
            break;
        }
    }
    FLASH_Lock();
    return ret;
}

uint8_t flash_erase(uint32_t address, uint16_t len)
{
    uint8_t ret = true;
    uint16_t pagecnt;
    uint32_t pageaddr;
    uint16_t i;
    pageaddr = (address / FLASH_PAGE_SIZE) * FLASH_PAGE_SIZE;   // page start address
    pagecnt = ((address % FLASH_PAGE_SIZE) + len) / FLASH_PAGE_SIZE;
    if (((address % FLASH_PAGE_SIZE) + len) % FLASH_PAGE_SIZE){
        pagecnt += 1;
    }
    FLASH_Unlock();
    FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
    for (i = 0; i < pagecnt; i++){
        if (FLASH_COMPLETE != FLASH_ErasePage(pageaddr + FLASH_PAGE_SIZE*i)){
            ret = false;
            break;
        }
    }
    FLASH_Lock();
    return ret;
}

uint8_t flash_update_buf[FLASH_PAGE_SIZE];
uint8_t flash_update(uint32_t address, uint8_t *buff, uint16_t len)
{
  uint32_t flash_page_addr = address/FLASH_PAGE_SIZE*FLASH_PAGE_SIZE;
  uint32_t flash_page_offset = address%FLASH_PAGE_SIZE;
  uint16_t count = 0;
  memset(flash_update_buf,0,FLASH_PAGE_SIZE);
  flash_read(flash_page_addr,flash_update_buf,FLASH_PAGE_SIZE);
  for(count=0;(count<len)&&((count+flash_page_offset)<FLASH_PAGE_SIZE);count++)
  {
    flash_update_buf[flash_page_offset+count] = buff[count];
  }
  flash_erase(flash_page_addr,1);
  flash_write(flash_page_addr,flash_update_buf,FLASH_PAGE_SIZE); 
  return true;
}








